import re
import random
from datetime import datetime

from flask import session

from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.utils.response_code import RET
from . import  passport_blue
from flask import abort, jsonify
from flask import current_app
from flask import make_response
from flask import request

from info import constants, db
from info import redis_store
from info.utils.captcha.captcha import captcha


@passport_blue.route('/image_code')
def get_image_code():
    #     '''1. 获取参数
    # 2. 校验参数
    # 3. 从redis获取图像验证码
    # 4. 对比验证码
    # 5. 生成短信验证码
    # 6. 保存验证码到redis
    # 7. 发送短信
    # 8. 返回成功信息'''
     image_code_id=request.args.get('image_code_id')
     if not image_code_id:
        return abort(403)
     name,text,image_data=captcha.generate_captcha()
     try:
         # 在info/__init__文件中: redis_store = None  # type: redis.StrictRedis
         redis_store.setex('image_code_id_'+image_code_id,constants.IMAGE_CODE_REDIS_EXPIRES,text)
         x=redis_store.get('image_code_id_'+image_code_id)
         print(x)
     except Exception as e:
         current_app.logger.error(e)
         return abort(500)
     response=make_response(image_data)
     response.headers['content-type']='image/jpg'
     return response

@passport_blue.route('/sms_code',methods=["POST"])
def send_sms():

    #获取请求里的json数据

    json_data=request.json
    mobile=json_data.get('mobile')
    image_code=json_data.get('image_code')
    image_code_id=json_data.get('image_code_id')
    #校验数据的完整性
    if not all([mobile,image_code,image_code_id]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数不全')

    #用正则验证手机号的正确性
    if not re.match(r'^1[3-9]\d{9}$',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机号输入有误')
    try:
        real_image_code=redis_store.get('image_code_id_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='redis数据库错误')

    #如果拿不到验证码,说明验证码已经过期
    if not real_image_code:
        return jsonify(errno=RET.NODATA,errmsg='验证码已过期')

    #不论验证码有没有输入正确,保存正确的验证码之后,都需要删除redis中的验证码
    try:
        redis_store.delete('image_code_id_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='redis数据库错误')

    #与数据库的验证码进行对比
    if image_code.lower()!=real_image_code.lower():
        return jsonify(errno=RET.DATAERR,errmsg='验证码输入有误')
    try:
        #先设置过滤器的查询条件,再取得过滤结果
        user=User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据库错误')

    #验证数据库中该手机号是否已经存在
    if user:
        return jsonify(errno=RET.DATAERR,errmsg='该手机号已经注册')
    sms_code_str='%06d'%random.randint(0,999999)
    current_app.logger.info(sms_code_str)

    #保存手机验证码到短信当中
    try:
        redis_store.setex('sms_code_'+mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code_str)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='数据库错误')
    # result=CCP().send_template_sms(mobile,[sms_code_str,5],1)
    # if result!='000000':
    #     return jsonify(errno=RET.THIRDERR,errmsg='验证码发送失败')
    return jsonify(errno=RET.OK,errmsg='验证码发送成功')


@passport_blue.route('/register', methods=['POST'])
def register():
    # 一. 获取参数
    mobile = request.json.get('mobile')
    sms_code = request.json.get('sms_code')
    password = request.json.get('password')

    # 二. 校验参数
    # 2.1 完整性
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")

    # 2.2 手机号
    if not re.match(r'^1[3456789][0-9]{9}$', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号填写错误")

    # 三. 逻辑处理
    # 1. 对比验证码
    # 1.1 从redis获取数据
    try:
        real_sms_code = redis_store.get('sms_code_' + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库错误")

    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码已过期或者手机号填写错误")

    # 1.2 对比短信验证码
    if real_sms_code != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="验证码填写错误")

    # 1.3 删除短信验证码
    try:
        redis_store.delete('sms_code_' + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="删除redis数据库错误")

    # 2. 用户注册
    # 2.1 判断是否注册
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询mysql数据库错误")

    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg="手机号已注册")

    # 2.2 创建用户模型
    user = User()
    user.nick_name = mobile  # 没有昵称, 先用手机号替代
    user.mobile = mobile
    # TODO (zhubo) 未做密码加密处理
    # pbkdf2:sha256:50000$HsSpOY1d$5bacb41165429cfb43ea61667d9c8aff6a6e40048e7efafb0140f99297238893
    # user.password_hash = generate_password_hash(password)
    # 开发中,对模型的处理一般都要放到模型中实现, 在视图函数中不要出现相关的运算代码
    user.password = password

    # MVC: model(模型: 除了定义,还包括对属性的计算) view(模板) control(控制, 将模型数据显示到视图中. 视图函数/接口)

    # 2.3 提交数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库错误")

    # 3. 设置登录
    # 存储时: 1. 常用信息如昵称或手机号 2. 用户id(用户可能存在一定的变化)
    # 场景: 用户先注册, 1小时候后发起修改用户名请求. 但是这中间该用户已被后台删除
    session['user_id'] = user.id
    session['nick_name'] = user.nick_name

    # 四. 返回数据
    return jsonify(errno=RET.OK, errmsg="注册成功")


@passport_blue.route('/login',methods=['POST'])
def login():
    #1.获取参数,手机号和密码
    json_data=request.json
    mobile=json_data.get('mobile')
    password=json_data.get('password')

    #2.验证参数的完整性和正确性
    if not all([mobile,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数不全')

    if not re.match(r'^1[3-9]\d{9}$',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机号输入有误')

    #3.对比密码和手机号,先验证手机号
    try:
        # 查询数据库中的对象时,先写条件,再写执行器 first() 或者all()
        user=User.query.filter_by(mobile=mobile).first()
    except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR,errmsg='数据库错误')
    # if not user:
    #     return jsonify(errno=RET.DATAERR,errmsg='用户名不存在')
    result=user.check_password(password)

    #4.如果密码错误,返回密码或者用户名错误
    if not result or not user:
        return jsonify(errno=RET.DATAERR,errmsg='用户名或者密码错误')

    #5.登陆成功则设置session
    session['mobile']=user.mobile
    session['user_id']=user.id
    session['nick_name']=user.nick_name
    user.last_login=datetime.now()
    return jsonify(errno=RET.OK,errmsg='登陆成功')

@passport_blue.route('/logout',methods=['POST'])
def logout():
    session.pop('nick_name',None)
    session.pop('user_id',None)
    session.pop('is_admin',False)
    return jsonify(errno=RET.OK,errmsg='登出成功')











# 登陆代码
#1.获取用户输入的手机号以及密码
# 2.判断是否有值为空
# 3.从数据库中取该手机号的密码,如果取不到，抛出“用户名或密码不正确”,并与用户输入的密码进行对比
# 4.错误则抛出错误 密码或者手机不正确。
# 5.正确的话 设置session session[nickname] session[mobile] session[ID]
# 6. user.最后登陆时间设置一下


#模板渲染
# 1.从session中取到userid
#2. 把user设为None 根据userid查询user 然后取得它所有的信息
# 3. data= user.to_dict()if user else NOne 然后渲染模板

#退出
#session.pop


